package com.koron.rating.classify;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.koron.bean.base.Response;
import com.koron.bean.system.staff.vo.EamUser;
import com.koron.common.core.annocation.CasUser;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.common.core.util.ExportExcelUtil;
import com.koron.common.core.util.StringUtils;
import com.koron.rating.change.bean.UnitCheckPo;
import com.koron.rating.classify.bean.*;
import com.koron.rating.classify.mapper.RatingUnitMapper;
import com.koron.rating.classify.services.UnitClassifyService;
import com.koron.rating.units.RatingUnits;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.koron.ebs.mybatis.ADOConnection;
import org.koron.ebs.mybatis.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author: rocky
 * @Date: 2022/1/6 15:54
 */
@RequestMapping("/UnitClassify")
@RestController
@Slf4j
@Api(tags = "设备评级-单元划分")
public class UnitClassifyController {

    private EamUser getEamUser() {
        return ThreadLocalContext.get();
    }

    private String getCurrDs() {
        return ThreadLocalContext.get().getCurrDs();
    }

    @Autowired
    private UnitClassifyService unitclassifyservice;

    @PostMapping("/insertBeOne")
    @ApiOperation(value = "新增部门 单个")
    public Response insert(@CasUser @ApiIgnore EamUser user, @RequestBody RatingUnitOneDto dto) {
        dto.setEquipmentId(dto.getDeptId());
        dto.setEquipmentName(dto.getDeptName());
        ArrayList<String> unitTypelist = CollUtil.newArrayList(dto.getUnitType());
        ArrayList<UnitCheckPo> checkPolist = CollUtil.newArrayList(new UnitCheckPo(dto.getEquipmentId(), dto.getEquipmentName(), dto.getUnitType()));
        // 查重
        ADOConnection.runTask(user.getCurrDs(), unitclassifyservice, "checkRepeat", void.class, unitTypelist, checkPolist, null);
        RatingUnitBean ratingunit = Convert.convert(RatingUnitBean.class, dto);
        return ADOConnection.runTask(user.getCurrDs(), new UnitClassifyService(), "insert", Response.class, ratingunit);
    }

    @PostMapping("/insertBatch")
    @ApiOperation(value = "新增单元 批量")
    public Response insertBatch(@CasUser @ApiIgnore EamUser user, @RequestBody RatingUnitBatchDto dto) {
        Assert.isFalse(StringUtils.isEmpty(dto.getDet()), "新增数据不能为空");
//        List<String> unitTypelist = dto.getDet().stream().map(RatingUnitOneDto::getUnitType).distinct().collect(Collectors.toList());
        List<String> unitTypelist = dto.getDet().stream().map(RatingUnitOneDto::getUnitType).distinct().collect(Collectors.toList());
        List<UnitCheckPo> checkPolist = dto.getDet().stream().map(r -> {
            return new UnitCheckPo(r.getEquipmentId(), r.getName(), dto.getUnitType());
        }).collect(Collectors.toList());
        // 查重
        ADOConnection.runTask(user.getCurrDs(), unitclassifyservice, "checkRepeat", void.class, unitTypelist, checkPolist, null);
        return ADOConnection.runTask(user.getCurrDs(), new UnitClassifyService(), "insertBatch", Response.class, dto);
    }

    @PostMapping("/update")
    @ApiOperation(value = "修改单元")
    public Response update(@CasUser @ApiIgnore EamUser user, @RequestBody RatingUnitBean ratingunit) {
        ArrayList<String> unitTypelist = CollUtil.newArrayList(ratingunit.getUnitType());
        ArrayList<UnitCheckPo> checkPolist = CollUtil.newArrayList(new UnitCheckPo(ratingunit.getEquipmentId(), ratingunit.getEquipmentName(), ratingunit.getUnitType()));
        // 查重
        ADOConnection.runTask(user.getCurrDs(), unitclassifyservice, "checkRepeat", void.class, unitTypelist, checkPolist, ratingunit.getId());
        return ADOConnection.runTask(user.getCurrDs(), unitclassifyservice, "update", Response.class, ratingunit);
    }

    @GetMapping("/delete")
    @ApiOperation(value = "删除单元")
    public Response delete(@CasUser @ApiIgnore EamUser user, String id) {
        return ADOConnection.runTask(user.getCurrDs(), unitclassifyservice, "delete", Response.class, id);
    }

    @GetMapping("/getById")
    @ApiOperation(value = "查询单个单元")
    public Response<RatingUnitBean> getById(String id) {
        return ADOConnection.runTask(ThreadLocalContext.get().getCurrDs(), unitclassifyservice, "getById", Response.class, id);
    }

//    //@GetMapping("/getTree")
//    @ApiOperation(value = "查询设备台账树形结构")
//    @Deprecated
//    public Response<List<RatingUnitBean>> getTree(@CasUser @ApiIgnore EamUser user){
//        return ADOConnection.runTask(user.getCurrDs(),unitclassifyservice, "getTree", Response.class);
//    }

    @GetMapping("/getTreeLazy")
    @ApiOperation(value = "查询设备单元树形结构（懒加载）")
    public Response<List<RatingUnitBean>> getTreeLazy(@CasUser @ApiIgnore EamUser user, String parentId) {
        return ADOConnection.runTask(user.getCurrDs(), unitclassifyservice, "getTreeLazy", Response.class, parentId);
    }

    @GetMapping("/getFloor")
    @ApiOperation(value = "获取层级列表")
    public Response<List<Select>> getFloor(@CasUser @ApiIgnore EamUser user, String parentId, String id) {
        return ADOConnection.runTask(user.getCurrDs(), unitclassifyservice, "getFloor", Response.class, parentId, id);
    }

    @GetMapping("/searchByName")
    @ApiOperation(value = "根据设单元称模糊查询")
    public Response<List<RatingUnitBean>> searchByName(@CasUser @ApiIgnore EamUser user, String name, String deptId) {
        return ADOConnection.runTask(user.getCurrDs(), unitclassifyservice, "searchByName", Response.class, name, deptId);
    }

    @GetMapping("/getParentIds")
    @ApiOperation(value = "获取某个节点的所有父节点")
    public Response<List<String>> getParentIds(@CasUser @ApiIgnore EamUser user, String id) {
        return ADOConnection.runTask(user.getCurrDs(), unitclassifyservice, "getParentIds", Response.class, id);
    }

//    @GetMapping("/getLeftUpperRatingUnitByDeptId")
//    @ApiOperation(value = "获取同组织下，最左上的设备台账")
//    public Response<RatingUnitBean> getLeftUpperRatingUnitByDeptId(@CasUser @ApiIgnore EamUser user, String deptId) {
//        return ADOConnection.runTask(user.getCurrDs(), unitclassifyservice, "getLeftUpperRatingUnitByDeptId", Response.class, deptId);
//    }

    @GetMapping("/changeSort")
    @ApiOperation(value = "同父级下 上下移")
    public Response<RatingUnitBean> changeSort(@CasUser @ApiIgnore EamUser user, RatingUnitSortDto dto) {
        return ADOConnection.runTask(user.getCurrDs(), unitclassifyservice, "changeSort", Response.class, dto);
    }


    @GetMapping("/queryRatingUnitTypeGroup")
    @ApiOperation(value = "各类型统计数")
    public Response<List<RatingUnitTypeGroupVo>> queryRatingUnitTypeGroup(@RequestParam("deptId") String deptId) {
        List<RatingUnitTypeGroupVo> list = ADOConnection.runTask(getCurrDs(), factory -> {
            List<RatingUnitTypeGroupVo> temlist = factory.getMapper(RatingUnitMapper.class).queryRatingUnitTypeGroup(deptId);
            int sum = temlist.stream().mapToInt(RatingUnitTypeGroupVo::getSubtotal).sum();
            temlist.stream().forEach(t -> t.setTotal(sum));
            return temlist;
        }, List.class);
        return Response.ok(list);
    }


    @GetMapping("/impGyxsb")
    @ApiOperation(value = "导入高压线设备")
    public Response<Tree> impGyxsb(@RequestParam(value = "id", defaultValue = "03040000000001") String id,
                                @RequestParam(value = "ratingId", defaultValue = "1555080449892438017") String ratingId) {
        // 设备台账高压线路id
        Tree tree = ADOConnection.runTask(getCurrDs(), factory -> {

            ImpEqBo topNode = new ImpEqBo();
            topNode.setId(id);

            // 所有高压线路
            List<ImpEqBo> querygyxlist = factory.getMapper(RatingUnitMapper.class).querygyx(id);

            TreeNodeConfig treeNodeConfig = new TreeNodeConfig();

            //转换器 注意这个 topNode.getId() 为 最顶级节点 id。 后面枝叶都依据此扩展
//        List<Tree<String>> treeList = TreeUtil.build(dblist, "03000000000001", treeNodeConfig,
            List<Tree<String>> treeList = TreeUtil.build(querygyxlist, topNode.getId(), treeNodeConfig,
                    (treeNode, node) -> {
                        node.setId(treeNode.getId());
                        node.setParentId(treeNode.getParentId());
                        node.setWeight(treeNode.getSort());    //排序权重
                        node.setName(treeNode.getName());
                        node.putExtra("typeId", treeNode.getTypeId());
                        node.putExtra("parentName", treeNode.getParentName());
                        node.putExtra("typeName", treeNode.getTypeName());
                        node.putExtra("floor", treeNode.getFloor());
                        node.putExtra("sort", treeNode.getSort());
                    });


            //补充根节点（顶级节点）基本能信息
            Tree toptree = new Tree(treeNodeConfig);
            toptree.setName("顶级节点");
            toptree.setId(topNode.getId());
            toptree.setChildren(treeList);                             //上面构建的树 放进来.   treeList可以对其他库树形结构进行拼接
            toptree.putExtra("typeId", topNode.getTypeId());
            toptree.putExtra("equipmentId", topNode.getId());
            toptree.putExtra("equipmentName", topNode.getName());
            toptree.putExtra("parentName", topNode.getParentName());
            toptree.putExtra("typeName", topNode.getTypeName());
            toptree.putExtra("floor", topNode.getFloor());
            toptree.putExtra("sort", topNode.getSort());
            return toptree;
        }, Tree.class);

        List<ImpEqBo> eqlist = new ArrayList();
        RatingUnits.recursionEq(CollUtil.newArrayList(tree), eqlist);

        List<RatingUnitBean> ratingunitlist = new ArrayList();
        for (ImpEqBo impEqBo : eqlist) {
            if (impEqBo.getName().equals("顶级节点")) {
                continue;
            }

            RatingUnitBean ratingUnitBean = new RatingUnitBean();
            ratingUnitBean.setId(impEqBo.getId());
            ratingUnitBean.setName(impEqBo.getName());
            // 设备高压线 等价于 评级电气室
            if (impEqBo.getParentId().equals(id)) {
                ratingUnitBean.setParentId(ratingId);
                ratingUnitBean.setParentName("电气室");
            } else {
                ratingUnitBean.setParentId(impEqBo.getParentId());
                ratingUnitBean.setParentName(impEqBo.getParentId());
            }
            ratingUnitBean.setTypeId(impEqBo.getTypeId());
            ratingUnitBean.setTypeName(impEqBo.getTypeName());
            ratingUnitBean.setDataSources(DateUtil.today() + "导入");
            ratingUnitBean.setDeptId("000343");
            ratingUnitBean.setSort(impEqBo.getSort());
            ratingUnitBean.setEquipmentId(impEqBo.getId());
            ratingUnitBean.setEquipmentName(impEqBo.getName());
            ratingUnitBean.setDeptName("维修部");
            ratingUnitBean.setUnitType("");
            ratingUnitBean.setUnitId("000232");
            ratingUnitBean.setUnitName("电气室");
            ratingUnitBean.setLevel(99);
            ratingUnitBean.setLevelPath("");
            ratingUnitBean.setLevelCode(impEqBo.getSort());

            ratingunitlist.add(ratingUnitBean);
        }

        Boolean aBoolean = ADOConnection.runTask(getCurrDs(), factory -> {
            RatingUnitMapper mapper = factory.getMapper(RatingUnitMapper.class);
            Lists.partition(ratingunitlist, 300).stream().forEach(p -> {
                mapper.batchInsert(p);
            });

            return true;
        }, Boolean.class);

        return Response.ok(tree);
    }

    @GetMapping("/buildGyxsb")
    @ApiOperation(value = "构建评级高压线设备")
    public Response<List> buildGyxsb(@RequestParam(value = "id", defaultValue = "1555080449892438017") String id,
                                  @RequestParam(value = "dataSources", defaultValue = "2022-09-06导入") String dataSources) {

        List list = ADOConnection.runTask(getCurrDs(), factory -> {
            RatingUnitMapper mapper = factory.getMapper(RatingUnitMapper.class);

            // 所有设备数据
            List<RatingUnitBean> ratingUnitBeanList = mapper.queryByDataSources(dataSources);

            // 电气室顶级节点
            RatingUnitBean topnode = mapper.selectByPrimaryKey(id);
            ratingUnitBeanList.add(topnode);

            TreeNodeConfig treeNodeConfig = new TreeNodeConfig();

            List<Tree<String>> treeList = TreeUtil.build(ratingUnitBeanList, topnode.getId(), treeNodeConfig,
                    (treeNode, node) -> {
                        node.setId(treeNode.getId());
                        node.setParentId(treeNode.getParentId());
                        node.setWeight(treeNode.getSort());    //排序权重
                        node.setName(treeNode.getName());

                        Field[] fields = ReflectUtil.getFields(RatingUnitBean.class);
                        Class<?> clazz = treeNode.getClass();
                        try {
                            // 扩展属性 ...
                            for (Field field : fields) {
                                field.setAccessible(true);
                                if (StrUtil.equalsAny(field.getName(), "id", "parentId", "name")) {
                                    continue;
                                }
                                clazz.getDeclaredField(field.getName());
                                node.putExtra(field.getName(), field.get(treeNode));
                            }
                        } catch (NoSuchFieldException e) {
                            log.error(e.getMessage(), e);
                        } catch (IllegalAccessException e) {
                            log.error(e.getMessage(), e);
                        }
                    });

            Tree tree = Convert.convert(Tree.class, topnode);
            tree.setChildren(treeList);
            List<RatingUnitBean> updatelist = new ArrayList();
            // 构建评级划分
//            recursionEq(factory, CollUtil.newArrayList(tree), updatelist, topnode);
            recursionEq(factory, tree.getChildren(), updatelist, topnode);

            Lists.partition(updatelist, 300).stream().forEach(p -> {
                mapper.updateBatchSelective(p);
            });

            return updatelist;
        }, List.class);

        return Response.ok(list);
    }



    // 正序递归 实体
    public static void recursionEq(SessionFactory factory, List<Tree> tree, List<RatingUnitBean> updatelist, RatingUnitBean parent) {
        for (Tree vo: tree) {
            RatingUnitBean cp = BeanUtil.copyProperties(vo, RatingUnitBean.class, "children");
            RatingUnitBean convert = Convert.convert(RatingUnitBean.class, cp);

            convert.setParentName(parent.getName());
            // 父级level+1
            convert.setLevel(parent.getLevel() + 1);
            convert.setFullPathCode(parent.getFullPathCode() + "/" + convert.getId());
            convert.setFullPathName(parent.getFullPathName() + "/" + convert.getName());
            List<String> split = StrUtil.split(convert.getFullPathName(), "/");
            convert.setUnitType(split.size()+"");
            if (split.size() == 6) {
                convert.setIscore(false);
            } else{
                convert.setIscore(true);
            }
            convert.setLevelPath(parent.getLevelPath() + "/" + convert.getSort());
            updatelist.add(convert);
            if (CollUtil.isNotEmpty(vo.getChildren())) {
                recursionEq(factory, vo.getChildren(), updatelist, convert);
            }
        }
    }


    @GetMapping("/updateRatingBz")
    @ApiOperation(value = "更新评级标准")
    public Response updateRatingBz(@RequestParam("deptId") String deptId) {
        ADOConnection.runTask(getCurrDs(), factory->{
            RatingUnitMapper mapper = factory.getMapper(RatingUnitMapper.class);
            mapper.updateRatingIdByDeptId(deptId);
            return true;
        }, Boolean.class);
        return Response.ok();
    }

    @GetMapping("/exportNoSqlRatingEq")
    @ApiOperation(value = "导出未关联标准设备")
    public void exportNoSqlRatingEq(@RequestParam("deptId") String deptId, HttpServletResponse response) {
        List<RatingUnitBean> list = ADOConnection.runTask(getCurrDs(), factory -> {
            RatingUnitMapper mapper = factory.getMapper(RatingUnitMapper.class);
            List<RatingUnitBean> bolist = mapper.queryByDeptIdAndRatingIdIsNull(deptId);
            return bolist.stream().map(new Function<RatingUnitBean, ExportNoSqlDto>() {
                @Override
                public ExportNoSqlDto apply(RatingUnitBean b) {
                    return new ExportNoSqlDto(b.getTypeName(), b.getName(), b.getParentName(), b.getFullPathName());
                }
            }).collect(Collectors.toList());
        }, List.class);

        try {
            ExportExcelUtil.exportExcel(list, ExportNoSqlDto.class, "未关联标准设备清单", response);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }


}
